﻿using System;
using System.IO;
using Wolfpack.Core;
using Wolfpack.Core.Checks;
using Wolfpack.Core.Interfaces.Entities;
using Wolfpack.Core.Notification;

namespace Wolfpack.Contrib.Checks.Registry
{
    public class RegistryCheck : HealthCheckBase<RegistryCheckConfig>
    {
        private FileInfo _stateFile;

        public RegistryCheck(RegistryCheckConfig config) : base(config)
        {
        }

        public override void Initialise()
        {
            var folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetType().Name);
            CreateStateFolder(folder);

            _stateFile = new FileInfo(Path.Combine(folder, _config.FriendlyId + ".txt"));
        }

        /// <summary>
        /// Checks the current registry value against the last known value.  If no known value exists or
        /// if the value has changed, send a message.
        /// </summary>
        public override void Execute()
        {
            var registryKey = Microsoft.Win32.Registry.LocalMachine;
            var registryValue = registryKey.GetSafeValue(_config.SubKey, _config.Keyname).ToString();

            string previousValue;

            if (LastStoredValueMatches(registryValue, out previousValue))
                return;

            StoreCurrentRegistryValue(registryValue);

            var payload = HealthCheckData.For(Identity, @"{0}\{1}={2}", 
                _config.SubKey, _config.Keyname, registryValue)
                .Failed()
                .AddProperty("PreviousValue", previousValue)
                .AddProperty("CurrentValue", registryValue)
                .AddTag(registryValue);
            Publish(NotificationRequestBuilder.For(_config.NotificationMode, payload).Build());
        }

        private void StoreCurrentRegistryValue(string registryValue)
        {
            using (var sw = new StreamWriter(_stateFile.FullName, false))
                sw.WriteLine(registryValue);
        }

        private static void CreateStateFolder(string folder)
        {
            try
            {
                Directory.CreateDirectory(folder);
            }
            catch
            {
                Logger.Debug("Unable to create state directory '{0}' for registry read.", folder);
            }           
        }

        private bool LastStoredValueMatches(string registryValue, out string previousValue)
        {
            if (_stateFile.Exists)
            {
                using (var sr = _stateFile.OpenText())
                {
                    previousValue = sr.ReadLine();
                    if (previousValue == registryValue)
                        return true;
                }
            }

            previousValue = string.Empty;
            return false;
        }

        protected override PluginDescriptor BuildIdentity()
        {
            return new PluginDescriptor
            {
                Description = "Registry HealthCheck",
                Name = _config.FriendlyId,
                TypeId = new Guid("44AFB612-40AB-42ce-8248-D632BC05DC17")
            };
        }
    }
}